home *** CD-ROM | disk | FTP | other *** search
- char *ckxv = "OS-9 tty I/O, 5A(08) 12 Oct 92";
-
- /* C K 9 T I O */
-
- /* C-Kermit interrupt, terminal control & i/o functions for os9/68k systems */
-
- /*
- Author: Peter Scholz
- Ruhr University Bochum, Department of analytical chemistry
- Federal Republic of Germany, February 1987
-
- Bob Larson (Blarson@ecla.usc.edu)
- Cleanup, fix timeouts, fix connect escape
- Rewrite ttinl for less overhead
-
- Edition: 5A(01)
- Chris Hemsing (Chris@lfm.rwth-aachen.de)
- Cleaned up timed i/o using F$Alarm
- Tmode/Xmode stuff
- Send break stuff
- All time related stuff new
-
- 07/25/91 Chris Hemsing minor bug fixes, changes for gnu (ansi) C
-
- 12/02/91 Bob Larson Blarson@usc.edu
- alarm() code was a nice idea, but doesn't work. Fixed back to
- code that will interupt i/o in progress. Minor cleanup.
- Retrofited current unix myread() code to speed things back up.
-
- 01/14/92 Chris Hemsing minor xmode bug fixes, sigmask <->longjump
- OS-9 does interrupt i/o, but bad drivers don't
- -> alarm code not reintroduced.
- Edition: 5A(05)
- Bob Larson conchk bug fix
- Edition: 5A(06)
- 03/04/92 Chris Hemsing ttopen: dup(0) fix, compare upper case
- Edition: 5A(06)
- 09/28/92 Chris Hemsing cccbrk bug fix
- Edition: 5A(06)
- 10/12/92 Chris Hemsing improved CTRL-E handling (catch)
-
- adapted from unix C-Kermit
- Author: Frank da Cruz (SY.FDC@CU20B),
- Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
- York. Permission is granted to any individual or institution to use this
- software as long as it is not sold for profit. This copyright notice must be
- retained. This software may not be included in commercial products without
- written permission of Columbia University.
- */
-
-
- #include <dir.h> /* Directory */
- #ifdef NULL
- #undef NULL
- #endif NULL
- #ifndef GREGORIAN
- #define GREGORIAN 0
- #define JULIAN 1
- #endif
- #include <signal.h> /* Interrupts */
- #include <errno.h>
- #include <sgstat.h> /* Set/Get tty modes */
- #include <sg_codes.h> /* setstat/getstat function codes */
- #include <setsys.h>
- #include <setjmp.h>
- #include <strings.h>
- #include <time.h>
- #include <modes.h> /* osk i/o modes S_IREAD, etc */
- #include "ckcdeb.h" /* Typedefs, formats for debug() */
-
- /* Maximum length for the name of a tty device */
-
- #ifndef DEVNAMLEN
- #define DEVNAMLEN MAXNAMLEN*4+2 /* leave room for / and terminating
- \0 */
- #endif /* not really an OS-9 restriction */
- /* *4 is arbitrary */
- /* nfm getstat call bug: SS_DevNm always
- copies all 32 bytes, nfm does the first
- part of the name => sum is more than
- 32 bytes
- e.g "term": all fine
- because 32 bytes incl. "term" are copied
- "n0/node1/term": "n0/node1/" done by nfm
- "term" is done by remote's scf
- (32 bytes) */
- char *ckxsys = " OS-9/68000";
-
- #define MYREAD /* use improved input code */
- /* Warning: untested without this defiend */
-
- /*
- Variables available to outside world:
-
- dftty -- Pointer to default tty name string, like "/dev/tty".
- dfloc -- 0 if dftty is console, 1 if external line.
- dfprty -- Default parity
- dfflow -- Default flow control
- ckxech -- Flag for who echoes console typein:
- 1 - The program (system echo is turned off)
- 0 - The system (or front end, or terminal).
- functions that want to do their own echoing should check this flag
- before doing so.
-
- Functions for assigned communication line (either external or console tty):
-
- syscleanup() -- System dependent shutdown
- sysinit() -- System dependent program initialization
- ttopen(ttname,local,mdmtyp,timo) -- Open the named tty for exclusive access.
- ttclos() -- Close & reset the tty.
- ttpkt(speed,flow) -- Put the tty in packet mode and set the speed.
- ttvt(speed,flow) -- Put the tty in virtual terminal mode.
- or in DIALING or CONNECTED modem control state.
- ttinl(dest,max,timo) -- Timed read line from the tty.
- ttinc(timo) -- Timed read character from tty.
- myread() -- Raw mode bulk buffer read, gives subsequent
- chars one at a time and simulates FIONREAD.
- myunrd(c) -- Places c back in buffer to be read (one only)
- ttchk() -- See how many characters in tty input buffer.
- ttxin(n,buf) -- Read n characters from tty (untimed).
- ttol(string,length) -- Write a string to the tty.
- ttoc(c) -- Write a character to the tty.
- ttflui() -- Flush tty input buffer.
- */
-
- /*
- Functions for console terminal:
-
- congm() -- Get console terminal modes.
- concb(esc) -- Put the console in single-character wakeup mode with no echo.
- conbin(esc) -- Put the console in binary (raw) mode.
- conres() -- Restore the console to mode obtained by congm().
- conoc(c) -- Unbuffered output, one character to console.
- conol(s) -- Unbuffered output, null-terminated string to the console.
- conola(s) -- Unbuffered output, array of strings to the console.
- conxo(n,s) -- Unbuffered output, n characters to the console.
- conchk() -- Check if characters available at console (bsd 4.2).
- Check if escape char (^\) typed at console (System III/V).
- coninc(timo) -- Timed get a character from the console.
- conint() -- Enable terminal interrupts on the console if not background.
- connoi() -- Disable terminal interrupts on the console if not background.
-
- Time functions
-
- msleep(m) -- Millisecond sleep
- ztime(s) -- Return date/time string
- rtimer() -- Reset timer
- gtimer() -- Get elapsed time since last call to rtimer()
- */
-
- /* Declarations */
-
- extern int errno; /* System call error return */
-
- /* dftty is the device name of the default device for file transfer */
- /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
-
- char *dftty; /* Remote by default, use normal */
- int dfloc = 0; /* controlling terminal name. */
-
- int dfprty = 0; /* Parity (0 = none) */
- int ttprty = 0; /* current parity */
- static int ttpmsk = 0377; /* Parity stripping mask. */
- int dfflow = 1; /* Xon/Xoff flow control */
- int backgrd = 0; /* Assume in foreground (no '&' ) */
-
- int ckxech = 0; /* 0 if system normally echoes console characters, else
- 1 */
-
- int ttypn = -1; /* TTY path number, also used in ck9con.c */
-
- int ttnproto = 0; /* Network protocol, 0 = none. */
- int ttcarr = CAR_AUT; /* Carrier handling mode. */
-
- char myttystr[DEVNAMLEN];
-
- /* Declarations of variables global within this module */
-
- static char ttnmsv[DEVNAMLEN]; /* always name of ttypn device */
- static char dfttystr[DEVNAMLEN];
- static int
- xlocal = 0; /* Flag for tty local or remote */
-
- static struct sgbuf /* sgtty info... */
- ttold, ttraw, tttvt, /* for communication line */
- ccold, ccraw, cccbrk; /* and for console */
-
-
- static time_t tcount; /* Elapsed time counter */
- static time_t timowhen; /* timeout time */
-
- static SIGTYP (*saval)() = NULL; /* For saving alarm handler */
- static jmp_buf sjbuf; /* Longjump buffers */
- static SIGTYP timerh();
-
- #define B50 0
- #define B75 1
- #define B110 2
- #define B134 3
- #define B150 4
- #define B300 5
- #define B600 6
- #define B1200 7
- #define B1800 8
- #define B2000 9
- #define B2400 10
- #define B3600 11
- #define B4800 12
- #define B7200 13
- #define B9600 14
- #define B19200 15
- #define B38400 16
-
- static unsigned short bdrts[] = {
- 50, 75, 110, 134, 150, 300, 600, 1200,
- 1800, 2000, 2400, 3600, 4800, 7200, 9600, 19200, 38400
- };
-
- /* for unix signal emulation */
-
- #define MAXSIG 4
- typedef VOID (*fptr)();
- fptr sigtbl[MAXSIG+1];
- fptr signal();
-
- syscleanup() {
- return 0; /* none needed */
- }
-
- /* S Y S I N I T -- System-dependent program initialization. */
-
- sysinit() {
- /* initialize unix signal emulation */
- register int i;
- register char *cp;
- VOID catch();
- char *getenv();
-
- for(i=0;i<=MAXSIG;i++)
- sigtbl[i] = SIG_DFL;
- intercept(catch);
- if(isatty(0)) { /* must disable buffering before io */
- setbuf(stdin,(char *)NULL);
- setbuf(stdout,(char *)NULL);
- }
- /* get terminal name from enviornment variable PORT,
- * use device of stderr as a backup
- */
- myttystr[0] = '/';
- if((cp = getenv("PORT")) == NULL) {
- if(_gs_devn(2, myttystr+1) < 0) return -1;
- } else strcpy(myttystr, cp);
- strcpy(dfttystr, myttystr);
- dftty = &dfttystr[0];
- backgrd = (isatty(0) && isatty(1)) ? 0 : 1;
- congm();
- return 0;
- }
-
- /* T T O P E N -- Open a tty for exclusive access. */
-
- /*
- Call with:
- ttname: character string - device name or network host name.
- lcl:
- If called with lcl < 0, sets value of lcl as follows:
- 0: the terminal named by ttname is the job's controlling terminal.
- 1: the terminal named by ttname is not the job's controlling terminal.
- But watch out: if a line is already open, or if requested line can't
- be opened, then lcl remains (and is returned as) -1.
- modem:
- Less than zero: ttname is a network host name.
- Zero or greater: ttname is a terminal device name.
- Zero means a local connection (don't use modem signals).
- Positive means use modem signals.
- timo:
- 0 = no timer.
- nonzero = number of seconds to wait for open() to return before timing out.
-
- Returns:
- 0 on success
- -5 if device is in use
- -4 if access to device is denied
- -3 if access to lock directory denied
- -2 upon timeout waiting for device to open
- -1 on other error
- */
-
- int
- ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem, timo; {
-
- char dev_buffer[DEVNAMLEN];
- debug(F111,"ttopen entry modem",ttname,modem);
- debug(F101," ttypn","",ttypn);
- debug(F101," lcl","",*lcl);
-
- if (ttypn > -1) /* if device already opened */
- {
- if (ustrncmp(ttname,ttnmsv,DEVNAMLEN))/* are new & old names equal? */
- /* compare ignoring case */
- ttclos(0); /* no, close old ttname, open new */
- else /* else same, ignore this call, */
- return(0); /* and return. */
- }
- if (timo < 0) timo = 0; /* Safety */
- if (setjmp(sjbuf)) /* Timer went off? */
- {
- debug(F100,"ttopen timout","",0); /* Get here on timeout. */
- return(-2); /* and return error code. */
- }
- else
- {
- if (timo)
- { /* Don't time out if timo == 0 */
- /* This won't work, since alarm() will not interupt i/o. */
- /* Unfortunatatly, there is no non-blocking open to replace */
- /* it with. blarson@usc.edu */
- /* Alarm will interrupt i/o when using a proper driver that */
- /* checks for pending signals smaller than deadly */
- /* chris@lfm.rwth-aachen.de */
- saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
- alarm((unsigned int)timo); /* Set it. */
- }
- strncpy(ttnmsv,ttname,DEVNAMLEN); /* keep ttnmsv corresp. to ttypn */
- dev_buffer[0] = '/';
- _gs_devn(0,&dev_buffer[1]); /* get name of stdin */
- if (*ttname=='\0' || ustrncmp(ttname,dev_buffer,DEVNAMLEN)==0)
- ttypn = open(ttname,S_IREAD|S_IWRITE);
- /* Try open for read/write; we cannot open own stdin non-share*/
- /* Don't simply dup(0) or dup(1); they might only be open
- for mere read (0) or mere write (1) */
- else
- ttypn = open(ttname,S_IREAD|S_IWRITE|S_ISHARE); /* Try to open for
- read/write nonshare*/
- if (timo)
- ttimoff(); /* Turn off timer */
- if (ttypn < 0) /* If couldn't open, fail. */
- {
- perror(ttname);
- if ((errno == E_DEVBSY) ||
- (errno == E_SHARE )) return(-5);
- return(-1);
- }
- }
- debug(F111,"ttopen ok",ttname,*lcl);
-
-
- /* Caller wants us to figure out if line is controlling tty */
-
- if (*lcl == -1)
- {
- if (isatty(0))
- { /* if stdin not redirected */
- dev_buffer[0] = '/';
- _gs_devn(0,&dev_buffer[1]); /* ...with real name of stdin */
- xlocal = (ustrncmp(ttname,dev_buffer,DEVNAMLEN) != 0);
- debug(F111," ttyname",dev_buffer,xlocal);
- }
- else /* Else, if stdin redirected... */
- {
- /* Just assume local, so "set speed" and similar commands will work */
- /* If not really local, how could it work anyway?... */
- xlocal = 1;
- debug(F101," redirected stdin","",xlocal);
- }
- }
-
- /* line locking not needed -- os9 has exclusive access flag on open */
-
- /* Got the line, now set the desired value for local. */
-
- if (*lcl < 0) *lcl = xlocal;
-
- /* Get tty device settings */
-
- _gs_opt(ttypn,&ttold); /* Get sgtty info */
- _gs_opt(ttypn,&ttraw); /* And a copy of it for packets*/
- _gs_opt(ttypn,&tttvt); /* And one for virtual tty service */
- debug(F101,"ttopen, ttypn","",ttypn);
- debug(F101," lcl","",*lcl);
- return(0);
- }
-
- /* T T C L O S -- Close the TTY */
-
- ttclos(foo) int foo; {
- if (ttypn < 0) return(0); /* Wasn't open. */
- if (xlocal) {
- if (tthang()) /* Hang up phone line */
- fprintf(stderr,"Warning, problem hanging up the phone\n");
- }
- ttres(); /* Reset modes. */
- /* Relinquish exclusive access if we might have had it... */
- close(ttypn); /* Close it. */
- debug (F101,"closed connection, ttypn","",ttypn);
- ttypn = -1; /* Mark it as closed. */
- return(0);
- }
-
- #ifdef MYREAD
-
- /* Private buffer for myread() and its companions. Not for use by anything
- * else. ttflui() is allowed to reset them to initial values. ttchk() is
- * allowed to read my_count.
- *
- * my_item is an index into mybuf[]. Increment it *before* reading mybuf[].
- *
- * A global parity mask variable could be useful too. We could use it to
- * let myread() strip the parity on its own, instead of stripping sign
- * bits as it does now.
- */
-
- #define MYBUFLEN 256
- static CHAR mybuf[MYBUFLEN]; /* Buffer, including push back */
- static int my_count = 0; /* Number of chars still in mybuf */
- static int my_item = -1; /* Last index read from mybuf[] */
-
- /* myread() -- Efficient read of one character from communications line.
- *
- * Uses a private buffer to minimize the number of expensive read() system
- * calls. Essentially performs the equivalent of read() of 1 character, which
- * is then returned. By reading all available input from the system buffers
- * to the private buffer in one chunk, and then working from this buffer, the
- * number of system calls is reduced in any case where more than one character
- * arrives during the processing of the previous chunk, for instance high
- * baud rates or network type connections where input arrives in packets.
- * If the time needed for a read() system call approaches the time for more
- * than one character to arrive, then this mechanism automatically compensates
- * for that by performing bigger read()s less frequently. If the system load
- * is high, the same mechanism compensates for that too.
- *
- * myread() is a macro that returns the next character from the buffer. If the
- * buffer is empty, mygetbuf() is called. See mygetbuf() for possible error
- * returns.
- *
- * This should be efficient enough for any one-character-at-a-time loops.
- * For even better efficiency you might use memcpy()/bcopy() or such between
- * buffers (since they are often better optimized for copying), but it may not
- * be worth it if you have to take an extra pass over the buffer to strip
- * parity and check for CTRL-C anyway.
- *
- * Note that if you have been using myread() from another program module, you
- * may have some trouble accessing this macro version and the private variables
- * it uses. In that case, just add a function in this module, that invokes the
- * macro.
- */
- #define myread() (--my_count < 0 ? mygetbuf() : 255 & (int)mybuf[++my_item])
-
- /* Specification: Push back up to one character onto myread()'s queue.
- *
- * This implementation: Push back characters into mybuf. At least one character
- * must have been read through myread() before myunrd() may be used. After
- * EOF or read error, again, myunrd() can not be used. Sometimes more than
- * one character can be pushed back, but only one character is guaranteed.
- * Since a previous myread() must have read its character out of mybuf[],
- * that guarantees that there is space for at least one character. If push
- * back was really needed after EOF, a small addition could provide that.
- *
- * myunrd() is currently not called from anywhere inside kermit...
- */
- #ifdef NOTUSED
- myunrd(ch) CHAR ch; {
- if (my_item >= 0) {
- mybuf[my_item--] = ch;
- ++my_count;
- }
- }
- #endif
-
- /* mygetbuf() -- Fill buffer for myread() and return first character.
- *
- * This function is what myread() uses when it can't get the next character
- * directly from its buffer. First, it calls a system dependent myfillbuf()
- * to read at least one new character into the buffer, and then it returns
- * the first character just as myread() would have done. This function also
- * is responsible for all error conditions that myread() can indicate.
- *
- * Returns: When OK => a positive character, 0 or greater.
- * When EOF => -2.
- * When error => -3, error code in errno.
- *
- * Older myread()s additionally returned -1 to indicate that there was nothing
- * to read, upon which the caller would call myread() again until it got
- * something. The new myread()/mygetbuf() always gets something. If it
- * doesn't, then make it do so! Any program that actually depends on the old
- * behaviour will break.
- *
- * The older version also used to return -2 both for EOF and other errors,
- * and used to set errno to 9999 on EOF. The errno stuff is gone, EOF and
- * other errors now return different results, although Kermit currently never
- * checks to see which it was. It just disconnects in both cases.
- *
- * Kermit lets the user use the quit key to perform some special commands
- * during file transfer. This causes read(), and thus also mygetbuf(), to
- * finish without reading anything and return the EINTR error. This should
- * be checked by the caller. Mygetbuf() could retry the read() on EINTR,
- * but if there is nothing to read, this could delay Kermit's reaction to
- * the command, and make Kermit appear unresponsive.
- *
- * The debug() call should be removed for optimum performance.
- */
- int
- mygetbuf() {
- my_count = myfillbuf();
- /* debug(F101, "myfillbuf read", "", my_count); */
- if (my_count <= 0)
- return(my_count < 0 ? -3 : -2);
- --my_count;
- return(255 & (int)mybuf[my_item = 0]);
- }
-
- /* myfillbuf():
- * System-dependent read() into mybuf[], as many characters as possible.
- *
- * Returns: OK => number of characters read, always more than zero.
- * EOF => 0
- * Error => -1, error code in errno.
- *
- * If there is input available in the system's buffers, all of it should be
- * read into mybuf[] and the function return immediately. If no input is
- * available, it should wait for a character to arrive, and return with that
- * one in mybuf[] as soon as possible. It may wait somewhat past the first
- * character, but be aware that any such delay lengthens the packet turnaround
- * time during kermit file transfers. Should never return with zero characters
- * unless EOF or irrecoverable read error.
- *
- * Correct functioning depends on the correct tty parameters being used.
- * Better control of current parameters is required than may have been the
- * case in older Kermit releases. For instance, O_NDELAY (or equivalent) can
- * no longer be sometimes off and sometimes on like it used to, unless a
- * special myfillbuf() is written to handle that. Otherwise the ordinary
- * myfillbuf()s may think they have come to EOF.
- *
- * If your system has a facility to directly perform the functioning of
- * myfillbuf(), then use it. If the system can tell you how many characters
- * are available in its buffers, then read that amount (but not less than 1).
- * If the system can return a special indication when you try to read without
- * anything to read, while allowing you to read all there is when there is
- * something, you may loop until there is something to read, but probably that
- * is not good for the system load.
- */
-
- /* This is for OSK. _gs_rdy returns the number
- * of characters available for reading. If none are available, wait
- * until something arrives, otherwise return all there is.
- * The OSK version needs to handle timeouts explicitly since
- * OSK alarm() does not interupt I/O. (Only done when filling buffer
- * to reduce overhead.)
- */
- int
- myfillbuf() {
- register int avail;
-
- (void) remove_alarm(); /* let's fake it instead */
- for(;;) {
- if (timowhen && time((time_t *)0) >= timowhen) { /*check for timeout*/
- timowhen = 0;
- if (sigtbl[MAXSIG] != SIG_DFL) (*sigtbl[MAXSIG])(SIGALRM);
- return -1;
- }
- if ((avail = _gs_rdy(ttypn)) > 0) break;
- sigmask(1);
- _ss_ssig(ttypn, SIGARB);
- sleep(1); /* interupted by signal if incoming char */
- _ss_rel(ttypn, SIGARB);
- }
-
- if (avail > MYBUFLEN)
- avail = MYBUFLEN;
-
- return(read(ttypn, mybuf, (int) avail));
- }
-
- #endif /* MYREAD */
- /* T T H A N G -- Hangup phone line */
-
- tthang() {
- /* if (ttypn < 0) return(0); /* Not open. */
- return 0; /* not implemented */
- }
-
-
- /* T T R E S -- Restore terminal to "normal" mode. */
-
- ttres() { /* Restore the tty to normal. */
- if (ttypn < 0) return(-1); /* Not open. */
- #ifdef XMODE
- if (xmode(ttold.sg_baud) < 0) return(-1);
- #endif
- tsleep(2); /* Wait for pending i/o to finish. */
- if (_ss_opt(ttypn,&ttold) < 0) return(-1); /* Restore sgtty stuff */
- return(0);
- }
-
- /* T T P K T -- Condition the communication line for packets. */
- /* or for modem dialing */
-
- /* If called with speed > -1, also set the speed. */
-
- /* Returns 0 on success, -1 on failure. */
-
- ttpkt(speed,flow,parity)
- long speed;
- int flow, parity;
- {
- int s;
- if (ttypn < 0) return(-1); /* Not open. */
- if (speed >-1)
- if ((s=ttsspd(speed/10)) <0) return(-1); /* Check the speed */
-
- ttprty = parity;
-
- ttraw.sg_case =
- ttraw.sg_backsp =
- ttraw.sg_delete =
- ttraw.sg_echo =
- ttraw.sg_alf =
- ttraw.sg_nulls =
- ttraw.sg_pause =
- ttraw.sg_bspch =
- ttraw.sg_dlnch =
- ttraw.sg_eorch =
- ttraw.sg_eofch =
- ttraw.sg_rlnch =
- ttraw.sg_dulnch =
- ttraw.sg_psch =
- ttraw.sg_kbich =
- ttraw.sg_kbach =
- ttraw.sg_bsech =
- ttraw.sg_tabcr = 0;
- if (speed >-1)
- ttraw.sg_baud = (char)s;
- if (flow==1) {
- ttraw.sg_xon = 0x11;
- ttraw.sg_xoff = 0x13;
- } else ttraw.sg_xon = ttraw.sg_xoff = 0;
- if(_ss_opt(ttypn,&ttraw) < 0) return(-1); /* set new modes . */
- ttflui(); /* Flush any pending input */
- return(0);
- }
-
- /* T T V T -- Condition communication line for use as virtual terminal */
-
- ttvt(speed,flow) long speed; int flow; {
-
- int s;
- if (ttypn < 0) return(-1); /* Not open. */
- if ((s=ttsspd(speed/10)) <0) return(-1); /* This speed not supported */
-
- tttvt.sg_case =
- tttvt.sg_backsp =
- tttvt.sg_delete =
- tttvt.sg_echo =
- tttvt.sg_alf =
- tttvt.sg_nulls =
- tttvt.sg_pause =
- tttvt.sg_bspch =
- tttvt.sg_dlnch =
- tttvt.sg_eorch =
- tttvt.sg_eofch =
- tttvt.sg_rlnch =
- tttvt.sg_dulnch =
- tttvt.sg_psch =
- tttvt.sg_kbich =
- tttvt.sg_kbach =
- tttvt.sg_bsech =
- tttvt.sg_tabcr = 0;
- tttvt.sg_baud = (char)s;
- if (flow==1) {
- tttvt.sg_xon = 0x11;
- tttvt.sg_xoff = 0x13;
- } else tttvt.sg_xon = tttvt.sg_xoff = 0;
- s = _ss_opt(ttypn,&tttvt); /* set new modes . */
- debug (F101,"ss_opt on tty was :","",s);
- return(0);
- }
-
- /* T T F L U I -- Flush tty input buffer */
-
- ttflui() {
- int n;
- char flushbuf[256];
-
- if (ttypn < 0) return(-1); /* Not open. */
- #ifdef MYREAD
- my_count = 0; /* initialize myread() stuff */
- my_item = -1;
- #endif
- while((n=_gs_rdy(ttypn))>0)
- read(ttypn, flushbuf, n>256 ? 256 : (unsigned int)n);
- return 0;
- }
-
- /* T T C H K -- Tell how many characters are waiting in tty input buffer */
- ttchk() {
- register int n;
-
- n = _gs_rdy(ttypn);
- if (n < 0) n = 0;
- #ifdef MYREAD
- if (my_count > 0) n += my_count;
- #endif
- return n;
- }
-
- /* T T X I N -- Get n characters from tty input buffer */
- /* Returns number of characters actually gotten, or -1 on failure */
- /* Intended for use only when it is known that n characters are actually */
- /* Available in the input buffer. */
-
- ttxin(n,buf) int n; CHAR *buf; {
- register int c;
- #ifdef MYREAD
- register CHAR *bp, *bpe;
- #else
- register int x;
- #endif
-
- ttpmsk = (ttprty) ? 0177 : 0377; /* Parity stripping mask. */
- debug(F101,"ttxin n","",n);
- #ifdef MYREAD
- for( bpe = (bp = buf) + n; (bp != bpe) && (c = myread()) >= 0; )
- *bp++ = c & ttpmsk;
- if (c < 0) return -1;
- *bp = '\0';
- return n;
- #else
- x = read(ttypn,(char *)buf,(unsigned int)n);
- if (ttprty) {
- for (c = 0; c < n; c++) buf[c] &= 0177;
- }
- if (x > 0) buf[x] = '\0';
- if (x < 0) x = -1;
- return(x);
- #endif
- }
-
- /* C O N I N T -- Console Interrupt setter */
- VOID
- conint(f,s) SIGTYP (*f)(), (*s)();
- {
- if (backgrd) return; /* must ignore signals in bkgrd */
- signal(SIGINT,f); /* console escape in pkt modes */
- }
-
-
- /* C O N N O I -- Reset console terminal interrupts */
- VOID
- connoi() { /* Console-no-interrupts */
- signal(SIGQUIT,(fptr)SIG_IGN);
- signal(SIGINT,(fptr)SIG_IGN);
- }
-
-
-
- /* T T O L -- Similar to "ttinl", but for writing. */
-
- ttol(s,n) int n; CHAR *s; {
- int x;
- debug(F101,"ttol: ttypn","",ttypn);
- if (ttypn < 0) return(-1); /* Not open. */
- x = write(ttypn,s,(unsigned int)n);
- debug(F111,"ttol",s,n);
- if (x < 0) debug(F101,"ttol failed","",x);
- return(x);
- }
-
-
- /* T T O C -- Output a character to the communication line */
-
- int
- #ifdef CK_ANSIC
- ttoc(char c)
- #else
- ttoc(c) char c;
- #endif /* CK_ANSIC */
- /* ttoc */{
- if (ttypn < 0) return(-1); /* Not open. */
- return(write(ttypn,&c,1));
- }
-
-
- /* T T I N L -- Read a record (up to break character) from comm line. */
- /*
- Reads up to "max" characters from the communication line, terminating on
- the packet-end character (eol), or timing out and returning -1 if the eol
- character not encountered within "timo" seconds. The characters that were
- input are copied into "dest" with their parity bits stripped if parity was
- selected. Returns the number of characters read. Characters after the
- eol are available upon the next call to this function.
-
- The idea is to minimize the number of system calls per packet, and also to
- minimize timeouts. This function is the inner loop of the program and must
- be as efficient as possible. The current strategy is to use myread().
-
- WARNING: this function calls parchk(), which is defined in another module.
- Normally, ckutio.c does not depend on code from any other module, but there
- is an exception in this case because all the other ck?tio.c modules also
- need to call parchk(), so it's better to have it defined in a common place.
- */
- #define CTRLC '\03'
-
- int
- #ifdef PARSENSE
- #ifdef CK_ANSIC
- ttinl(CHAR *dest, int max,int timo, CHAR eol, CHAR start)
- #else
- ttinl(dest,max,timo,eol,start) int max,timo; CHAR *dest, eol, start;
- #endif /* CK_ANSIC */
- #else /* not PARSENSE */
- #ifdef CK_ANSIC
- ttinl(CHAR *dest, int max,int timo, CHAR eol)
- #else
- ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
- #endif /* __SDTC__ */
- #endif /* PARSENSE */
- /* ttinl */ {
-
- CHAR ch;
-
- if (ttypn < 0) return(-1); /* Not open. */
-
- debug(F101,"ttinl max","",max);
- debug(F101,"ttinl timo","",timo);
-
- *dest = '\0'; /* Clear destination buffer */
- if (timo < 0) timo = 0; /* Safety */
- if (setjmp(sjbuf)) { /* Timer went off? */
- debug(F100,"ttinl timout","",0); /* Get here on timeout. */
- debug(F110," with",(char *) dest,0);
- return(-1); /* and return error code. */
- } else {
- register int i, n; /* local variables */
- int ccn = 0;
- #ifdef PARSENSE
- int flag = 0;
-
- debug(F000,"ttinl start","",start);
- flag = 0; /* Start of packet flag */
- #endif /* PARSENSE */
-
- if (timo) { /* Don't time out if timo == 0 */
- saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
- alarm((unsigned int)timo); /* Set it. */
- }
- ttpmsk = (ttprty) ? 0177 : 0377; /* Set parity stripping mask. */
-
- /* Now read into destination, stripping parity and looking for the */
- /* the packet terminator, and also for two Ctrl-C's typed in a row. */
-
- i = 0; /* Destination index */
- debug(F101,"ttinl eol","",(int)eol);
-
- #ifdef MYREAD
- while (i < max-1) {
- debug(F101,"ttinl i","",i);
- if ((n = myread()) < 0) {
- debug(F101,"ttinl myread failure, n","",n);
- debug(F101,"ttinl myread errno,","",errno);
- break;
- }
- #else
- while ((i < max-1) && (n = read(ttyfd, &ch, 1)) > 0) {
- n = ch;
- #endif /* MYREAD */
-
- #ifdef PARSENSE
- if ((flag == 0) && ((n & 0x7f) == start)) flag = 1;
- if (flag) dest[i++] = n & ttpmsk;
- #else
- dest[i++] = n & ttpmsk;
- #endif /* PARSENSE */
- if ((n & 0x7f) == CTRLC) { /* Check for ^C^C */
- if (++ccn > 1) { /* If we got 2 in a row, bail out. */
- if (timo) { /* Clear timer. */
- ttimoff();
- }
- fprintf(stderr,"^C...\r\l"); /* Echo Ctrl-C */
- return(-2);
- }
- } else ccn = 0; /* Not ^C, so reset ^C counter, */
-
- #ifdef PARSENSE
- if (flag == 0) {
- debug(F101,"ttinl skipping","",n);
- continue;
- }
- #endif /* PARSENSE */
-
- /* Check for end of packet */
-
- if ((n & 0x7f) == eol) {
- debug(F101,"ttinl got eol","",(int)eol);
- dest[i] = '\0'; /* Yes, terminate the string, */
- /* debug(F101,"ttinl i","",i); */
- #ifdef PARSENSE
- /* Here's where we actually check and adjust the parity. */
- /* The major flaw here is if parity is NONE (ttprty = 0) and the packets */
- /* really do have no parity, then parchk() is called for every packet. */
- /* In practice, this doesn't really harm efficiency noticably, but it would */
- /* be better if ttinl() had a way of knowing to stop doing this once a */
- /* particular file transfer had been started and checked. */
- if (ttprty == 0) {
- if ((ttprty = parchk(dest,start,i)) > 0) {
- int j;
- debug(F101,"ttinl senses parity","",ttprty);
- debug(F110,"ttinl packet before",dest,0);
- ttpmsk = 0x7f;
- for (j = 0; j < i; j++)
- dest[j] &= 0x7f; /* Strip parity from packet */
- debug(F110,"ttinl packet after ",dest,0);
- } else debug(F101,"parchk","",ttprty);
- }
- #endif /* PARSENSE */
- if (timo) { /* Turn off timer. */
- ttimoff();
- }
- debug(F111,"ttinl got", dest,i);
- return(i);
- }
- } /* end of while() */
- if (timo) /* Turn off timer. */
- ttimoff();
- return(-1);
- }
- }
-
- /* T T I N C -- Read a character from the communication line */
- /*
- On success, returns the character that was read, >= 0.
- On failure, returns -3 on internal error, -2 on communication disconnect,
- -1 on timeout and other
- */
- int
- ttinc(timo) int timo; {
- CHAR ch = 0;
- int n = 0;
-
- if (ttypn < 0) return(-1); /* Not open. */
- if (timo <= 0) { /* Untimed. */
- /* not realy untimed, ckudia.c uses alarm() */
- #ifdef MYREAD
- /* comm line failure returns -1 thru myread, so no &= 0377 */
- n = myread(); /* Wait for a character... */
- /* debug(F101,"ttinc n","",n); */
- #else
- while ((n = read(ttypn,&ch,1)) == 0) /* Wait for a character. */
- /* Shouldn't have to loop in ver 5A. */
- ;
- /* debug(F000,"ttinc","",ch); */
- return( (n < 1) ? -3 : (ch & ttpmsk) );
- #endif /* MYREAD */
- } else {
- saval = signal(SIGALRM,timerh); /* Timed, set up timer. */
- alarm((unsigned int)timo);
- if (setjmp(sjbuf)) {
- n = -1;
- } else {
- #ifdef MYREAD
- n = myread(); /* If managing own buffer... */
- debug(F101,"ttinc myread","",n);
- #else
- n = timoread(ttypn,(char *)&ch,1); /*Otherwise call the system.*/
- debug(F101,"ttinc read","",n);
- if (n > 0)
- n = ch & 255;
- else
- n = (n < 0) ? -3 : -2; /* Special return codes */
- #endif /* MYREAD */
- }
- ttimoff(); /* Turn off timer */
- }
- return( (n < 0) ? n : (n & ttpmsk) ); /* Return masked char or neg. */
- }
-
- /* T T S N D B -- Send a BREAK signal */
-
- ttsndb()
- {
- struct sgbuf before;
- int i;
- if (ttypn < 0) return(-1); /* Not open. */
- #ifndef XMODE
- if (send_break(ttypn) == 0) return(0); /* all fine done by driver */
- if (errno!=E_UNKSVC) return(-1); /*should have been unknown service call*/
- if (_gs_opt(ttypn,&before) < 0) return(-1); /* din't get old speed */
- for (i=B50; i<before.sg_baud; i++) /* try to switch to a lower speed */
- {
- if (ttsspd((int)bdrts[i]/10) != -1) break;
- }
- if (i == before.sg_baud) return(-1); /* no lower speed supported */
- #else
- if (_gs_opt(ttypn,&before) < 0) return(-1); /* din't get old speed */
- ttsspd((int)bdrts[B300]/10);/* xmode always return success, since it only
- patches device descriptor */
- #endif
- write(ttypn,"\0",1);
- write(ttypn,"\0",1); /* send two zeroes */
- msleep(400); /* wait chars to appear (50 baud == 400 milli seconds */
- ttsspd((int)bdrts[before.sg_baud]/10); /* restore old baud rate*/
- return(0);
- }
-
- VOID
- rtimer() {
- tcount = time( (time_t *) 0 );
- }
-
-
- /* G T I M E R -- Get current value of elapsed time counter in seconds */
-
- int
- gtimer() {
- int x;
- x = (int) (time( (time_t *) 0 ) - tcount);
- return( (x < 0) ? 0 : x );
- }
-
- /* Z T I M E -- Return date/time string */
- VOID
- ztime(s) char **s;
- {
- time_t t;
- t = time((time_t*)NULL);
- if (t != (time_t)-1)
- *s =ctime(&t);
- else
- *s = "Ddd Mmm 00 00:00:00 0000\n"; /* Return dummy in asctime() format */
- }
-
- /* C O N G M -- Get console terminal modes. */
-
- /*
- Saves current console mode, and establishes variables for switching between
- current (presumably normal) mode and other modes.
- */
-
- congm() {
- if (!isatty(0)) return(-1); /* only for real ttys */
- _gs_opt(0,&ccold); /* Structure for restoring */
- _gs_opt(0,&cccbrk); /* For setting CBREAK mode */
- cccbrk.sg_echo =
- cccbrk.sg_pause =
- cccbrk.sg_eofch =
- cccbrk.sg_psch = 0; /* kermit interpreter uses CTRL-W */
-
- _gs_opt(0,&ccraw); /* For setting RAW mode */
- ccraw.sg_case =
- ccraw.sg_backsp =
- ccraw.sg_delete =
- ccraw.sg_echo =
- ccraw.sg_alf =
- ccraw.sg_nulls =
- ccraw.sg_pause =
- ccraw.sg_bspch =
- ccraw.sg_dlnch =
- ccraw.sg_eorch =
- ccraw.sg_eofch =
- ccraw.sg_rlnch =
- ccraw.sg_dulnch =
- ccraw.sg_psch =
- ccraw.sg_kbich =
- ccraw.sg_kbach =
- ccraw.sg_bsech =
- ccraw.sg_tabcr =
- ccraw.sg_xon =
- ccraw.sg_xoff = 0;
- return(0);
- }
-
-
- /* C O N C B -- Put console in cbreak mode. */
- /* we can ignore esc since conchk() works on OS-9, no need for a special esc */
- /* Returns 0 if ok, -1 if not */
-
- int
- #ifdef CK_ANSIC
- concb(char esc)
- #else
- concb(esc) char esc;
- #endif /* CK_ANSIC */
- /* concb */ {
- int x;
- if (!isatty(0)) return(0); /* only for real ttys */
- ckxech = 1; /* Program can echo characters */
- x = _ss_opt(0,&cccbrk) | _ss_opt(1,&cccbrk);
- debug(F101,"console set to cbreak mode","",esc);
- return(x);
- }
-
- /* C O N B I N -- Put console in binary mode */
-
- /* we can ignore esc since conchk() works on OS-9, no need for a special esc */
- /* Returns 0 if ok, -1 if not */
-
- int
- #ifdef CK_ANSIC
- conbin(char esc)
- #else
- conbin(esc) char esc;
- #endif /* CK_ANSIC */
- /* conbin */ {
- if (!isatty(0)) return(0); /* only for real ttys */
- ckxech = 1; /* Program can echo characters */
- _ss_opt(0,&ccraw);
- _ss_opt(1,&ccraw); /* set new modes . */
- debug(F101,"console switched to raw mode","",esc);
- return(0);
- }
-
-
- /* C O N R E S -- Restore the console terminal */
-
- conres() {
- if(!isatty(0)) return 0; /* only for real ttys with known modes*/
- tsleep(2);
- ckxech = 0; /* OS-9 will echo chars */
- return(_ss_opt(0,&ccold)| _ss_opt(1,&ccold)); /* Restore controlling tty */
- }
-
- /* C O N O C -- Output a character to the console terminal */
- int
- #ifdef CK_ANSIC
- conoc(char c)
- #else
- conoc(c) char c;
- #endif /* CK_ANSIC */
- /* conoc */ {
- return((write(1,&c,1)>0) ? 1:0);
- }
-
- /* C O N X O -- Write x characters to the console terminal */
- /*VOID*/
- int
- conxo(x,s) char *s; int x; {
- write(1,s,(unsigned int)x);
- }
-
- /* C O N O L -- Write a line to the console terminal */
- /*VOID*/
- int
- conol(s) char *s; {
- int len;
- len = strlen(s);
- write(1,s,(unsigned int)len);
- }
-
- /* C O N O L L L -- Output a string followed by LF */
- static VOID
- conolll(s) char *s; {
- conol(s);
- write(1,"\l",1);
- }
-
- /* C O N O L A -- Write an array of lines to the console terminal */
- /*VOID */
- int
- conola(s) char *s[]; {
- int i;
- for (i=0 ; *s[i] ; i++) conolll(s[i]);
- }
-
- /* C O N O L L -- Output a string followed by CRLF */
- /*VOID*/
- int
- conoll(s) char *s; {
- conol(s);
- write(1,"\r\l",2);
- }
-
- /* C O N C H K -- Return how many characters available at console */
- conchk()
- {
- int x;
- x=_gs_rdy(0);
- if(x<0) x=0; /* always return 0 irrespective the type of error */
- /* e.q. /nil would return E_UNKSVC and conchk is only */
- /* checked on != 0 anyway, Bob Larson */
- debug (F101,"conchk","",x);
- return x;
- }
-
- /* C O N I N C -- Get a character from the console */
- int
- coninc(timo) int timo; {
- int n = 0; CHAR ch;
-
- if (timo <= 0 ) { /* Untimed. */
- n = read(0, (char *)&ch, 1); /* Read a character. */
- ch &= 0377;
- if (n > 0) /* Return the character if read ok */
- return(ch);
- else /* otherwise... */
- {
- debug(F101, "coninc(0) errno","",errno);
- return(-1); /* Return -1 as error indication */
- }
- }
- if (setjmp(sjbuf)) n = -2;
- else {
- saval = signal(SIGALRM,timerh); /* Timed read, so set up timer */
- alarm((unsigned int)timo);
- n = timoread(0, (char *)&ch, 1);
- ttimoff(); /* Turn off timer */
- ch &= 0377;
- }
- if (n > 0) return(ch);
- else
- return(-1);
- }
-
- /* emulate unix signal functions */
- fptr
- signal(sig,func)
- int sig;
- fptr func;
- {
- fptr temp;
- if (sig < MAXSIG) {
- temp = sigtbl[sig];
- sigtbl[sig] = func;
- return temp;
- }
- if (sig == SIGALRM) {
- temp = sigtbl[MAXSIG];
- sigtbl[MAXSIG] = func;
- return temp;
- }
- return (fptr)-1;
- }
-
- VOID
- catch(sig) register int sig;{
- register fptr temp;
-
- if(sig==SIGARB) return; /* nothing to do with i/o signals */
- if(sig < MAXSIG) {
- if ((temp=sigtbl[sig])==SIG_DFL) doexit(sig,-1);
- if(temp!=(SIGTYP (*)())SIG_IGN)
- (*temp)(sig);
- else
- {
- if (sig == SIGQUIT) /* output ceises on CTRL-E typed, so notify */
- stdin->_flag |= _ERR;
- }
- return;
- }
- if(sig == SIGALRM) {
- if ((temp=sigtbl[MAXSIG])==SIG_DFL) return;
- if (temp!=(SIGTYP (*)())SIG_IGN) (*temp)(sig);
- return;
- }
- doexit(sig,-1);
- }
-
- int isatty(path)
- int path;
- {
- struct sgbuf buffer;
- return((_gs_opt(path,&buffer)<0) ? 0 : buffer.sg_class == 0);
- }
-
- /*********************************************************************/
- int msleep(m_secs) /* sleeps at least !! (not exact) m_secs milli seconds */
- register int m_secs;
- {
- register unsigned int i;
- register int tick_rate;
- if ((tick_rate = _getsys(D_TckSec,2)) < 0) return(-1); /* clock not on */
- i = (unsigned int)(((double)m_secs*(double)tick_rate)/1000.0);
- tsleep(i+2); /* +1 for rounding and another
- +1 because tsleep is accurate not more than +/-(!) 1 tick */
- return(0);
- }
- /**********************************************************************/
- psuspend(foo) int foo;
- {
- return(-1);
- }
-
- long ttgspd() /* Get current tty speed */
- {
- struct sgbuf buffer;
- if (ttypn < 0) return(-1);
- if(_gs_opt(ttypn,&buffer) < 0) return(-1);
- return(bdrts[buffer.sg_baud]);
- }
-
-
- /* T T S C A R R -- Set ttcarr variable, controlling carrier handling.
- *
- * 0 = Off: Always ignore carrier. E.g. you can connect without carrier.
- * 1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect.
- * 2 = Auto: For "modem direct": The same as "Off".
- * For real modem types: Heed carrier during connect, but ignore
- * it anytime else. Compatible with pre-5A C-Kermit versions.
- *
- * As you can see, this setting does not affect dialing, which always ignores
- * carrier (unless there is some special exception for some modem type). It
- * does affect ttopen() if it is set before ttopen() is used. This setting
- * takes effect on the next call to ttopen()/ttpkt()/ttvt(). And they are
- * (or should be) always called before any communications is tried, which
- * means that, practically speaking, the effect is immediate.
- *
- * Of course, nothing of this applies to remote mode (xlocal = 0).
- *
- * Someone has yet to uncover how to manipulate the carrier in the BSD
- * environment (or any non-termio using environment). Until that time, this
- * will simply be a no-op for BSD.
- *
- * Note that in previous versions, the carrier was most often left unchanged
- * in ttpkt()/ttvt() unless they were called with DIALING or CONNECT. This
- * has changed. Now it is controlled by ttcarr in conjunction with these
- * modes.
- */
- ttscarr(carrier) int carrier; {
- ttcarr = carrier;
- debug(F101, "ttscarr","",ttcarr);
- return(ttcarr);
- }
-
- /* T T G M D M -- Get modem signals */
- /*
- Looks for the modem signals CTS, DSR, and CTS, and returns those that are
- on in as its return value, in a bit mask as described for ttwmdm. Returns:
- -3 Not implemented
- -2 if the line does not have modem control
- -1 on error.
- >= 0 on success, with a bit mask containing the modem signals that are on.
- */
- ttgmdm()
- {
- return(-3);
- }
-
- /* T T S S P D -- Set the transmission of tty to ten times the argument */
-
- ttsspd(speed) int speed; {
- int s;
- struct sgbuf before;
- debug (F101,"ttsspd: speed(cps):","",speed);
- if (ttypn < 0) return(-1);
- switch (speed) {
- case 5: s = B50; break;
- case 7: s = B75; break;
- case 11: s = B110; break;
- case 13: s = B134; break;
- case 15: s = B150; break;
- case 30: s = B300; break;
- case 60: s = B600; break;
- case 120: s = B1200; break;
- case 180: s = B1800; break;
- case 200: s = B2000; break;
- case 240: s = B2400; break;
- case 360: s = B3600; break;
- case 480: s = B4800; break;
- case 720: s = B7200; break;
- case 960: s = B9600; break;
- case 1920: s = B19200; break;
- case 3840: s = B38400; break;
- case 888: return(-1); /* no 75/1200 split speed */
- default: return -1;
- }
- _gs_opt(ttypn,&before);
- before.sg_baud = (char)s;
- #ifdef XMODE
- xmode((char)s); /* xmode open and closes => new options
- => restore as they were before */
- return(_ss_opt(ttypn,&before) < 0 ? -1 : s);
- #else
- return(_ss_opt(ttypn,&before) < 0 ? -1 : s);
- #endif
- }
-
- #ifdef XMODE
- int /* change the line tty speed via xmode, special hack for bad drivers*/
- xmode(os9_speed) char os9_speed;
- {
- char command[DEVNAMLEN+17]; /* e.g. xmode baud=38400 = 17 chars */
- char devicename[DEVNAMLEN];
- long old_speed;
- if ((old_speed = ttgspd()) < 0) return(-1);
- devicename[0] = '/';
- _gs_devn(ttypn,&devicename[1]);
- sprintf(command,"xmode %s baud=%d",devicename,bdrts[os9_speed]);
- debug (F110,"xmode command = ",command,0);
- debug (F101,"xmode baud","",os9_speed);
- zsyscmd(command);
- close(ttypn); /* hopefully not iniz'ed */
- if ((ttypn=open(devicename,0x43)) < 0) /* no open with new speed anymore*/
- {
- sprintf(command,"xmode %s baud=%d",devicename,old_speed);
- zsyscmd(command); /* restore old speed */
- ttypn=open(devicename,0x43); /* now it should work again */
- return (-1);
- }
- return(os9_speed);
- }
- #endif
- VOID
- ttimoff() { /* Turn off any timer interrupts */
- alarm(0);
- if (saval)
- signal(SIGALRM,saval);
- else
- signal(SIGALRM,(fptr)SIG_DFL);
- saval = NULL;
- }
-
- int alarm(secs) unsigned int secs;
- /* after secs seconds the signal SIGALRM will be sent */
- /* 0 will clear the alarm */
- {
- if (secs) {
- timowhen = time((time_t *)0) + secs;
- return(add_alarm(secs,SIGALRM));
- }
- timowhen = 0;
- return(remove_alarm());
- }
-
- /* read from serial device with working timeout */
- int
- timoread(ttypn, cp, n)
- int ttypn;
- char *cp;
- int n;
- {
- if (timowhen == 0) return read(ttypn, cp, n);
- (void) remove_alarm();
- for(;;) {
- if (_gs_rdy(ttypn) >= n) return read(ttypn, cp, n);
- if (time((time_t *)0) >= timowhen) {
- timowhen = 0;
- if (sigtbl[MAXSIG] != SIG_DFL) (*sigtbl[MAXSIG])(SIGALRM);
- return -1;
- }
- _ss_ssig(ttypn, SIGARB);
- sleep(1); /* interupted by _ss_ssig if incoming char */
- _ss_rel(ttypn, SIGARB);
- }
- }
-
- /* Timeout handler for communication line input functions */
- static SIGTYP
- timerh(sig) int sig;{
- ttimoff();
- sigmask(-1); /* we are in an intercept routine but do not perform
- a F$RTE (done implicitly but rts). => we have to
- decrement the sigmask as F$RTE does. Warning:
- longjump only restores the cpu registers NOT the
- fpu registers. So, don't use fpu at all or at
- least don't use common fpu (double or float)
- register variables */
- longjmp(sjbuf,1);
- }
- int ustrncmp(a2,a3,d4) /*string compare but ignore upper and lower case*/
- register char *a2,*a3;
- register int d4;
- {
- while((--d4>=0)&&(_toupper(*a2)==_toupper(*a3)))
- {
- if (*a3++ == '\0') return 0;
- a2++;
- }
- return (d4 < 0) ? 0 : *a2-*a3;
- }
-